package com.gitee.wsl.ext.any

import com.gitee.wsl.concurrent.api.SuspendRunnable
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract

/**
 * 效果等同于 if(){}，条件达成执行闭包，它不同于if的是，它具有返回值，可以用于一些条件赋值、可空初始化，例如：
 * ```
 * var some:String? = null
 * if (isTrue){
 *   some = "xxxx"
 * }
 * ```
 * 这种初始化赋值可以被改写成：
 * ```
 * val some = runIf(isTrue){ "xxx" }
 * ```
 * 之所以写这个函数是因为 `if-else` 表达式支持赋值但是 `if` 不支持
 */
@OptIn(ExperimentalContracts::class)
fun <T, R> T.runIf(condition: Boolean = true,  block: T.() -> R): R? {
    contract {
        callsInPlace(block, InvocationKind.AT_MOST_ONCE)
        returnsNotNull() implies condition
    }
    return this.run { block.takeIf { condition }?.invoke(this) }
}


suspend fun Boolean.runIf(block: SuspendRunnable) {
   if(this) block.run()
}


/**
 * Calls the specified function block with [t1] and [t2] as its arguments if [t1] and [t2] are not null.
 * Returns the function block’s result if it was called, and `null` if it wasn’t.
 */
inline fun <T1, T2, R> ifNotNull(t1: T1?, t2: T2?, onNotNull: (T1, T2) -> R): R? =
    if (t1 != null && t2 != null) {
        onNotNull(t1, t2)
    } else {
        null
    }

/**
 * Calls the specified function block with [t1], [t2], and [t3] as its arguments if [t1], [t2], and [t3] are not null.
 * Returns the function block’s result if it was called, and `null` if it wasn’t.
 */
inline fun <T1, T2, T3, R> ifNotNull(t1: T1?, t2: T2?, t3: T3?, onNotNull: (T1, T2, T3) -> R): R? =
    if (t1 != null && t2 != null && t3 != null) {
        onNotNull(t1, t2, t3)
    } else {
        null
    }

inline fun <reified T, R> ifNotNull(
    vararg elements: T?,
    closureSafe: () -> R
): R? = if (elements.all { it != null }) {
    closureSafe()
} else {
    null
}